package lion.framework.core.web.path;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;

import lion.dev.lang.MapJ;

/**
 * 一个处理路径参数的工具类,可提取路径中的参数或将参数映射到路径中。
 *
 * <pre>
 * time   2013 2013-4-24 上午11:31:57
 * mail   hl_0074@sina.com
 * </pre>
 *
 * @author lion
 */
public class ParameterizedPath {

	public static final Pattern parameterPattern = Pattern.compile("\\{((\\w+):?(\\w+)?)\\}");

	/**
	 * 获取请求路径中的参数
	 */
	public static MapJ getParameters(String pathPattern, String path) {

		String[] patterns = splitNode(pathPattern);
		String[] paths = splitNode(path);

		if (patterns.length != paths.length) { return new MapJ(); }

		MapJ param = new MapJ();
		for (int i = 0; i < patterns.length; i++) {
			extractParam(param, patterns[i], paths[i]);
		}
		return param;
	}

	/**
	 * 替换模式路径中的参数，获得实际路径
	 */
	public static String mapPath(String path, MapJ param) {

		if (param == null || param.isEmpty()) { return path; }

		Matcher m = parameterPattern.matcher(path);

		if (!m.find()) { return path; }
		m.reset();

		StringBuffer sbu = new StringBuffer();
		while (m.find()) {
			m.appendReplacement(sbu, param.getString(m.group(2), ""));
		}
		m.appendTail(sbu);

		return sbu.toString();
	}

	public static boolean isParameteredPath(String path) {

		if (StringUtils.isBlank(path)) { return false; }

		Matcher m = parameterPattern.matcher(path);
		return m.find();
	}

	private static void extractParam(MapJ param, String pattern, String path) {

		Matcher m = parameterPattern.matcher(pattern);
		if (!m.find()) { return; }
		m.reset();

		StringBuffer sbu = new StringBuffer();
		List<String> paramNames = new ArrayList<>();
		while (m.find()) {
			String parameterName = m.group(2);
			paramNames.add(parameterName);
			String p = "([^/]+)";
			if ("int".equals(m.group(3))) {
				p = "(\\\\d+)";
			} else if ("number".equals(m.group(3))) {
				p = "(-?\\\\d+\\\\.?\\\\d?)";
			}
			m.appendReplacement(sbu, p);
		}
		m.appendTail(sbu);
		String pathPattern = sbu.toString();

		Pattern p = Pattern.compile(pathPattern, Pattern.CASE_INSENSITIVE);

		Matcher matcher = p.matcher(path);
		if (matcher.find()) {
			for (int i = 0; i < matcher.groupCount() && i < paramNames.size(); i++) {
				param.put(paramNames.get(i), matcher.group(i + 1));
			}
		}
	}

	private static String[] splitNode(String src) {

		if (StringUtils.isBlank(src)) { return null; }

		return StringUtils.split(src.trim(), "/");
	}

}
